package bll

import (
  "gitlab.local/backend/proto/dto"
  "go-micro.dev/v4/broker"
  "google.golang.org/protobuf/proto"
  client "signal/client/broker"
  log "signal/collector/logger"
  "signal/event"
  "signal/lib/trace_log"
  "signal/model"
  "signal/utils"
)

var MQ = &mq{}

type mq struct {
}

func (m *mq) init() func() {
  // register event listener
  event.E.Register(event.DeviceStatusChange, m.eventHandle)
  event.E.Register(event.DeviceLocationReport, m.eventHandle)
  event.E.Register(event.DeviceBatteryReport, m.eventHandle)
  event.E.Register(event.DeviceSignalReport, m.eventHandle)
  event.E.Register(event.DeviceControlReport, m.eventHandle)
  event.E.Register(event.DeviceAlarm, m.eventHandle)
  event.E.Register(event.DeviceFault, m.eventHandle)
  event.E.Register(event.DeviceFaultCheck, m.eventHandle)
  event.E.Register(event.DeviceOTA, m.eventHandle)

  return func() {
    event.E.Unregister(event.DeviceStatusChange, m.eventHandle)
    event.E.Unregister(event.DeviceLocationReport, m.eventHandle)
    event.E.Unregister(event.DeviceBatteryReport, m.eventHandle)
    event.E.Unregister(event.DeviceSignalReport, m.eventHandle)
    event.E.Unregister(event.DeviceControlReport, m.eventHandle)
    event.E.Unregister(event.DeviceAlarm, m.eventHandle)
    event.E.Unregister(event.DeviceFault, m.eventHandle)
    event.E.Unregister(event.DeviceFaultCheck, m.eventHandle)
    event.E.Unregister(event.DeviceOTA, m.eventHandle)
  }
}

// received report data and publish it to RabbitMQ
func (m *mq) eventHandle(e event.Event, data interface{}) {
  var (
    err   error
    topic model.Topic
    body  []byte
  )

  sn := ""
  switch e {
  case event.DeviceStatusChange:
    topic = model.MQEventStatus

    d := data.(*dto.DeviceStatus)
    if body, err = proto.Marshal(d); err != nil {
      log.Errorf("marshal data to proto error: %s", err)
      return
    }
    sn = d.Sn
  case event.DeviceLocationReport:
    topic = model.MQEventLocation

    d := data.(*dto.Location)
    if body, err = proto.Marshal(d); err != nil {
      log.Errorf("marshal data to proto error: %s", err)
      return
    }
    sn = d.Sn
  case event.DeviceFault:
    topic = model.MQEventFault

    d := data.(*dto.Fault)
    if body, err = proto.Marshal(d); err != nil {
      log.Errorf("marshal data to proto error: %s", err)
      return
    }
    sn = d.Sn
  case event.DeviceFaultCheck:
    topic = model.MQEventFaultCheck

    d := data.(*dto.FaultCheck)
    if body, err = proto.Marshal(d); err != nil {
      log.Errorf("marshal data to proto error: %s", err)
      return
    }
    sn = d.Sn
  case event.DeviceAlarm:
    topic = model.MQEventAlarm

    d := data.(*dto.Alarm)
    if body, err = proto.Marshal(d); err != nil {
      log.Errorf("marshal data to proto error: %s", err)
      return
    }
    sn = d.Sn
  case event.DeviceBatteryReport:
    topic = model.MQEventBattery

    d := data.(*dto.BatteryInfo)
    if body, err = proto.Marshal(d); err != nil {
      log.Errorf("marshal data to proto error: %s", err)
      return
    }
    sn = d.Sn
  case event.DeviceSignalReport:
    topic = model.MQEventSignal

    d := data.(*dto.Signal)
    if body, err = proto.Marshal(d); err != nil {
      log.Errorf("marshal data to proto error: %s", err)
      return
    }
    sn = d.Sn
  case event.DeviceControlReport:
    topic = model.MQEventControl

    d := data.(*dto.Controller)
    if body, err = proto.Marshal(d); err != nil {
      log.Errorf("marshal data to proto error: %s", err)
      return
    }
    sn = d.Sn
  case event.DeviceOTA:
    topic = model.MQEventOTA
    switch data.(type) {
    case *dto.OTAUpgradeNtf:
      d := data.(*dto.OTAUpgradeNtf)
      if body, err = proto.Marshal(d); err != nil {
        log.Errorf("marshal data to proto error: %s", err)
        return
      }
      sn = d.Sn
      break
    case *dto.UpgradeBSC22Data:
      d := data.(*dto.UpgradeBSC22Data)
      if body, err = proto.Marshal(d); err != nil {
        log.Errorf("marshal data to proto error: %s", err)
        return
      }
      sn = d.Sn
      break
    }
  }

  if sn != "" {
    trace_log.DebugLogger(sn, string(topic), utils.ToJsonString(data))
  }

  log.Debugf("publish mq msg,event:%s,topic:%s,msg body:%s", string(e), string(topic), utils.ToJsonString(data))
  if err = client.PubSub.Publish(string(topic), &broker.Message{Body: body}); err != nil {
    log.Errorf("publish data to rabbit error: %s", err)
    return
  }
}
